﻿using Domain;
using ErrorCode;
using Infrastructure;
using Infrastructure.Redis;
using MediatR;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Microsoft.IdentityModel.Tokens;
using RabbitTraceability.Api.Applications.Command;
using System;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Security.Claims;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace RabbitTraceability.Api.Applications.CommandHandler
{
    /// <summary>
    /// 用户登录命令处理器
    /// </summary>
    public class UserLoginCommandHandler : IRequestHandler<UserLoginCommand, string>
    {
        private readonly IRepository<UserInfo> _userRepository;
        private readonly IConfiguration _configuration;
        private readonly ILogger<UserLoginCommandHandler> _logger;
        private readonly IRedisHelper _redisHelper;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="userRepository">用户仓储</param>
        /// <param name="configuration">配置</param>
        /// <param name="logger">日志记录器</param>
        /// <param name="redisHelper">Redis帮助类</param>
        public UserLoginCommandHandler(
            IRepository<UserInfo> userRepository,
            IConfiguration configuration,
            ILogger<UserLoginCommandHandler> logger,
            IRedisHelper redisHelper)
        {
            _userRepository = userRepository;
            _configuration = configuration;
            _logger = logger;
            _redisHelper = redisHelper;
        }

        /// <summary>
        /// 处理用户登录请求
        /// </summary>
        /// <param name="request">登录请求</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>JWT令牌</returns>
        public async Task<string> Handle(UserLoginCommand request, CancellationToken cancellationToken)
        {
            // 检查请求参数
            if (string.IsNullOrEmpty(request.Username) || string.IsNullOrEmpty(request.Password))
            {
                throw new ApiException(ResultCode.参数错误, "用户名或密码不能为空");
            }
            
            //// 验证验证码
            //if (string.IsNullOrEmpty(request.CaptchaGuid) || string.IsNullOrEmpty(request.CaptchaCode))
            //{
            //    throw new ApiException(ResultCode.参数错误, "验证码不能为空");
            //}

            try
            {
                // 从Redis获取验证码
                //string redisKey = $"Captcha:String:{request.CaptchaGuid}";
                //string? storedCaptcha = await _redisHelper.GetStringAsync(redisKey);
                
                //// 检查验证码是否存在
                //if (string.IsNullOrEmpty(storedCaptcha))
                //{
                //    _logger.LogWarning("登录失败: 验证码已过期或不存在, GUID: {CaptchaGuid}", request.CaptchaGuid);
                //    throw new ApiException(ResultCode.验证码错误, "验证码已过期或不存在");
                //}
                
                //// 验证码比较（不区分大小写）
                //if (!string.Equals(storedCaptcha, request.CaptchaCode, StringComparison.OrdinalIgnoreCase))
                //{
                //    _logger.LogWarning("登录失败: 验证码错误, GUID: {CaptchaGuid}", request.CaptchaGuid);
                //    throw new ApiException(ResultCode.验证码错误, "验证码错误");
                //}
                
                //// 验证成功后删除验证码（一次性使用）
                //await _redisHelper.RemoveAsync(redisKey);
                //_logger.LogInformation("验证码验证成功: {CaptchaGuid}", request.CaptchaGuid);

                // 查询用户信息
                var user = _userRepository.GetAll().FirstOrDefault(u => u.Username == request.Username && !u.IsDeleted);

                // 检查是否有匹配的用户
                if (user == null)
                {
                    _logger.LogWarning("登录失败: 用户名 {Username} 不存在", request.Username);
                    throw new ApiException(ResultCode.UserNotFound, "用户不存在");
                }

                // 验证密码
                if (!VerifyPassword(request.Password, user.Password))
                {
                    _logger.LogWarning("登录失败: 用户 {Username} 密码错误", request.Username);
                    throw new ApiException(ResultCode.PasswordIncorrect, "密码错误");
                }

                // 检查用户状态
                if (user.Status == 0)
                {
                    _logger.LogWarning("登录失败: 用户 {Username} 已被禁用", request.Username);
                    throw new ApiException(ResultCode.UserDisabled, "用户已被禁用");
                }

                // 生成JWT令牌
                var token = GenerateJwtToken(user);

                // 更新用户信息
                try
                {
                    await _userRepository.UpdateAsync(user);
                }
                catch (Exception ex)
                {
                    // 记录更新失败，但不影响登录
                    _logger.LogError(ex, "更新用户信息失败: {Username}", request.Username);
                }

                _logger.LogInformation("用户 {Username} 登录成功", request.Username);
                return token;
            }
            catch (ApiException)
            {
                // 重新抛出API异常
                throw;
            }
            catch (Exception ex)
            {
                // 记录其他异常
                _logger.LogError(ex, "登录过程中发生未处理的异常: {Message}", ex.Message);
                throw new ApiException(ResultCode.服务器错误, "登录失败，请稍后再试");
            }
        }

        /// <summary>
        /// 生成JWT令牌
        /// </summary>
        /// <param name="user">用户信息</param>
        /// <returns>JWT令牌字符串</returns>
        private string GenerateJwtToken(UserInfo user)
        {
            var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
            var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);

            // 设置过期时间
            double expiresInHours;
            if (!double.TryParse(_configuration["Jwt:ExpiresInHours"], out expiresInHours))
            {
                expiresInHours = 24; // 默认24小时
            }

            var claims = new[]
            {
                new Claim("UserId", user.UserId),
                new Claim("Username", user.RealName ?? user.Username), // 如果RealName为空，则使用Username
                new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString())
            };

            var token = new JwtSecurityToken(
                issuer: _configuration["Jwt:Issuer"],
                audience: _configuration["Jwt:Audience"],
                claims: claims,
                expires: DateTime.Now.AddHours(expiresInHours),
                signingCredentials: credentials);

            return new JwtSecurityTokenHandler().WriteToken(token);
        }

        /// <summary>
        /// 验证密码
        /// </summary>
        /// <param name="inputPassword">输入的密码</param>
        /// <param name="storedPassword">存储的密码</param>
        /// <returns>是否匹配</returns>
        private bool VerifyPassword(string inputPassword, string storedPassword)
        {
            // TODO: 实现密码哈希验证
            // 目前为简单比较，后续应改为哈希比较
            return inputPassword == storedPassword;
        }

        /// <summary>
        /// 计算密码哈希
        /// </summary>
        /// <param name="password">密码明文</param>
        /// <returns>密码哈希值</returns>
        private string HashPassword(string password)
        {
            // TODO: 实现密码哈希算法
            // 示例: 使用SHA256
            using (var sha256 = SHA256.Create())
            {
                var hashedBytes = sha256.ComputeHash(Encoding.UTF8.GetBytes(password));
                return Convert.ToBase64String(hashedBytes);
            }
        }
    }
}
